package com.apex.utils;

import com.apex.env.BaseEnv;
import com.apex.plugin.BasePlugin;

import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;

public class RegisteredPlugin {

    private static ConfigPackage configPackage;

    /** Get full qualified class name by reflection api, ignore case. */
    private String buildClassFullQualifier(String pluginName, PluginType classType) throws Exception {
        if (pluginName.split("\\.").length == 1) {
            String className = null;
            Iterable<? extends BasePlugin> plugins = null;
            switch (classType) {
                case SOURCE:
                    className = configPackage.sourcePackage()+"."+pluginName;
                    Class baseSource = Class.forName(className);
                    plugins = ServiceLoader.load(baseSource);
                    break;
                case TRANSFORM:
                    className = configPackage.transformPackage()+"."+pluginName;
                    Class baseTransform = Class.forName(className);
                    plugins = ServiceLoader.load(baseTransform);
                    break;
                case SINK:
                    className = configPackage.sinkPackage()+"."+pluginName;
                    Class baseSink = Class.forName(className);
                    plugins = ServiceLoader.load(baseSink);
                    break;
                default:
                    break;
            }

            String qualifierWithPackage = className;
            for (BasePlugin plugin : plugins) {
                Class serviceClass = plugin.getClass();
                String serviceClassName = serviceClass.getName();
                String clsNameToLower = serviceClassName.toLowerCase();
                if (clsNameToLower.equals(qualifierWithPackage.toLowerCase())) {
                    return serviceClassName;
                }
            }
            return qualifierWithPackage;
        } else {
            return pluginName;
        }
    }

    /**
     * instance PluginType
     *
     * @param type
     * @param engineName
     * @param <T>
     * @return
     */
    public <T extends BasePlugin> List<T> createPlugins(PluginType type, String engineName) {

        List<T> basePluginList = new ArrayList<>();
        try {
            final String className = buildClassFullQualifier(engineName, type);
            T t = (T) Class.forName(className).newInstance();
            basePluginList.add(t);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return basePluginList;
    }

    /**
     * data prepare process using plugin
     *
     * @param env
     * @param plugins
     */
    public static void prepare(BaseEnv env, List<? extends BasePlugin>... plugins) {
        for (List<? extends BasePlugin> pluginList : plugins) {
            pluginList.forEach(plugin -> {
                plugin.setConfig(env.getConfig());
                plugin.prepare(env);
            }
            );
        }
    }
    public void configEngine(String engine){
        configPackage = new ConfigPackage(engine);
    }
}
